package com.ddh.codeduck.infra.minio.utils;


import com.ddhcodeduck.common.exception.BusinessException;
import com.ddhcodeduck.common.exception.ErrorCode;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import io.minio.StatObjectArgs;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * MinIO 工具类，封装常用文件操作
 */
@Component
public class MinioUtils {

    @Resource
    private MinioClient minioClient;

    @Value("${minio.bucket-name}")
    private String bucketName;

    @Value("${minio.endpoint}")
    private String endpoint;

    /**
     * 上传文件到 MinIO
     *
     * @param file 要上传的文件
     * @return 文件访问路径（预签名 URL）
     */
    @SneakyThrows
    public String upload(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null || originalFilename.isEmpty()) {
            throw new BusinessException(ErrorCode.FILE_EMPTY_ERROR);
        }

        // 使用时间戳 + 原始文件名，避免重复
        String dateStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String fileName = dateStr + "-" + originalFilename;

        // 上传到 MinIO
        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(fileName)
                        .stream(file.getInputStream(), file.getSize(), -1)
                        .contentType(file.getContentType())
                        .build()
        );

        // 拼接访问路径（需要在文件服务器里面将bucket设置为public）
        return getPublicFileUrl(fileName);
    }


    /**
     * 删除文件
     *
     * @param fileName 文件名
     * @return 是否删除成功
     */
    public boolean delete(String fileName) {
        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(bucketName)
                            .object(fileName)
                            .build()
            );
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 获取文件是否存在
     *
     * @param fileName 文件名
     * @return 是否存在
     */
    public boolean exists(String fileName) {
        try {
            minioClient.statObject(
                    StatObjectArgs.builder()
                            .bucket(bucketName)
                            .object(fileName)
                            .build()
            );
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 直接构造文件访问路径（bucket 必须为 public）
     *
     * @param fileName 文件名
     * @return 文件访问路径
     */
    public String getPublicFileUrl(String fileName) {
        return endpoint + "/" + bucketName + "/" + fileName;
    }
}
